package restaurant;

import java.util.ArrayList;

import restaurant.iterators.Iterator;
import restaurant.iterators.RatingsIterator;

/**
 * Represents comments submitted by restaurant customers. The
 * {@code CustomerComments} class is a collection of {@code Comment} objects. In
 * order to access a {@code Comment}, the program must go through the
 * {@code CustomerComments} class.
 * 
 * @author Odessa
 * @see Comment
 * @see Rating
 */

public class CustomerComments
{

	/** The list of comments. */
	private ArrayList<Comment> customerComments;

	/** The item ratings. */
	private ArrayList<Comment> itemRatings;

	/** The comment number. */
	private int commentNumber = 1;



	/**
	 * Instantiates the customer comments.
	 */
	public CustomerComments() {
		customerComments = new ArrayList<Comment>();
		itemRatings = new ArrayList<Comment>();
	}



	/**
	 * Creates a new comment. The {@code commentNumber} is used so that each
	 * comment created has a unique comment number. After the comment is
	 * created, it is added to the customerComments and the
	 * <code>commentNumber</code> gets incremented.
	 * 
	 * @param comment the comment to be submitted.
	 * @return the newly created comment.
	 */
	public Comment addComment(String comment)
	{
		Comment c = new Comment(commentNumber, comment);
		add(customerComments, c);
		commentNumber++;

		return c;
	}



	/**
	 * Creates a new item rating. After the rating is created, it is added to
	 * the customerComments and the {@code commentNumber} gets incremented.
	 * 
	 * @param itemNo the item number of the item being rated.
	 * @param rating the item's rating.
	 * @param comment the comment of this rating.
	 * @return the newly created comment.
	 */
	public Comment addRating(int itemNo, int rating, String comment)
	{
		Rating r = new Rating(commentNumber, itemNo, rating, comment);
		add(itemRatings, r);
		commentNumber++;

		return r;
	}



	/**
	 * Creates a new item rating without a comment associated to it. After the
	 * rating is created, it is added to the customerComments and the
	 * {@code commentNumber} gets incremented.
	 * 
	 * @param itemNo the item number of the item being rated.
	 * @param rating the item's rating.
	 * @return the newly created comment.
	 */
	public Comment addRating(int itemNo, int rating)
	{
		Rating r = new Rating(commentNumber, itemNo, rating);
		add(itemRatings, r);
		commentNumber++;

		return r;
	}



	/**
	 * Adds the {@code comment} to the {@code list} specified. Takes a comment
	 * and appends it to the end of the list.
	 * 
	 * @param list the list to add the comment to.
	 * @param comment the comment to be added.
	 */
	private void add(ArrayList<Comment> list, Comment comment)
	{
		list.add(comment);
	}



	/**
	 * Deletes a comment. It first finds the comment in the customerComments and
	 * then deletes it.
	 * 
	 * @param commentNo the comment number of the comment to delete.
	 */
	public void delete(int commentNo)
	{
		Comment comment = find(commentNo);
		customerComments.remove(comment);
	}



	/**
	 * Finds a comment. It looks at all the comments in the customerComments and
	 * returns the comment with the specified comment number.
	 * 
	 * @param commentNo the comment number of the comment to find.
	 * @return the comment matching the comment number entered.
	 */
	private Comment find(int commentNo)
	{
		Comment comment = null;

		for (Comment c : customerComments) {
			int id = c.getCommentNo();

			if (id == commentNo) {
				comment = c;
				break;
			}
		}

		return comment;
	}



	/**
	 * Updates a comment. Comments are initially set as not being offensive. If
	 * however the manager determines that a comment should be marked as
	 * offensive, this method is used to change the comment's offensive status.
	 * It first finds the comment and then sets its offensive status to
	 * <code>true</code>.
	 * 
	 * @param commentNo the comment number of the offensive comment.
	 */
	public void update(int commentNo)
	{
		Comment comment = find(commentNo);
		comment.setOffensive();
	}



	/**
	 * Gets the comments.
	 * 
	 * @return the list of comments.
	 */
	public ArrayList<Comment> getComments()
	{
		return customerComments;
	}



	/**
	 * Gets an iterator of type {@code RatingsIterator} to iterate through an
	 * item's rating. It creates a new iterator and returns it.
	 * 
	 * @param itemNo the item number of the menu item whose ratings are being
	 *            retrieved.
	 * @return the iterator to view the ratings by the item number.
	 * @see RatingsIterator
	 */
	public Iterator getRatingsIterator(int itemNo)
	{
		return new RatingsIterator(itemRatings, itemNo);
	}



	/**
	 * Calculates the average rating of an item. Calls the
	 * <code>getByItemIterator</code> method to retrieve an iterator to traverse
	 * the item ratings. If the iterator has more comments, then the comment is
	 * retrieved and the rating is added to the sum while the number of ratings
	 * is incremented. When there aren't any more ratings for the item, the the
	 * average is calculated and returned.
	 * 
	 * @param itemNo the item to calculate the average rating of.
	 * @return the average rating of the item.
	 */
	public float calcAvgRating(int itemNo)
	{
		int num = 0;
		int sum = 0;
		float avg;
		Rating comment;
		Iterator iterator = getRatingsIterator(itemNo);

		while (iterator.hasNext()) {
			comment = (Rating) iterator.next();
			sum += comment.getRating();
			num++;
		}

		avg = sum / num;

		return avg;
	}
}
